package cn.yqx.bankshop.goods.config;

import cn.yqx.bankshop.constants.HttpConstant;
import cn.yqx.bankshop.goods.esutil.ESResult;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ParameterMode;
import org.apache.ibatis.session.Configuration;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;


import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Component
@Slf4j
public class ESClient {
    @Value("${elasticsearch.host}")
    String host ;
    @Value("${elasticsearch.port}")
    String port ;

    private static final String QUERY_STR = "query" ;

    private final Configuration configuration = new DSLConfiguration();

    public String generateDsl(String mapperId, Object param) {
        MappedStatement statement = configuration.getMappedStatement(mapperId);
        BoundSql boundSql = statement.getBoundSql(param) ;
        String dslStr = this.getAllSql(boundSql) ;
        JSONObject json = JSON.parseObject(dslStr) ;
        log.info(json.toJSONString());
        return json.toString();
    }

    public String getAllSql(BoundSql boundSql)  {
        String dslStr = boundSql.getSql() ;
        StringBuilder builder = new StringBuilder(dslStr) ;
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        Map<String,Object> parameterObject = (Map<String, Object>) boundSql.getParameterObject();
        int startIndex = 0 ;
        if (parameterMappings != null) {
            for (int i = 0; i < parameterMappings.size(); i++) {
                //获取某个参数
                ParameterMapping parameterMapping = parameterMappings.get(i);
                if (parameterMapping.getMode() != ParameterMode.OUT) {
                    Object value = "";
                    //参数的名字，属性
                    String propertyName = parameterMapping.getProperty();

                    if (boundSql.hasAdditionalParameter(propertyName)) {
                        value = boundSql.getAdditionalParameter(propertyName);
                    }else{
                        value = parameterObject.get(propertyName) ;
                    }
                    startIndex = builder.toString().indexOf("?",0);
                    StringBuilder str = new StringBuilder() ;
                    if(value instanceof String){
                        str.append("\"").append( value).append("\"") ;
                    }else {
                        str.append( value) ;
                    }
                    builder.replace(startIndex,startIndex+1,str.toString()) ;

                }
            }
        }
        return builder.toString() ;
    }

    public ESResult sendQuery(String index, String mapperId, Object param ) {
        String dslStr = this.generateDsl(mapperId,param) ;

        HttpHeaders headers = new HttpHeaders();

        headers.set(HttpConstant.CONTENT_TYPE, HttpConstant.APPLICATION_JSON);
        String url = HttpConstant.HTTP_KEY+host+":"+port+"/" + index + "/_search";
        HttpEntity<String> requestEntity = new HttpEntity<String>(dslStr, headers);
        RestTemplate restTemplate = new RestTemplate();
        String resoult = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class).getBody() ;
        JSONObject json = JSONObject.parseObject(resoult);
        JSONObject hits = json.getJSONObject("hits") ;
        long total = hits.getJSONObject("total").getLong("value");
        JSONArray hitsArray = hits.getJSONArray("hits") ;

        JSONArray sourceArray = new JSONArray() ;

        for(Object hitjson : hitsArray){
            hitjson = (JSONObject) hitjson ;
            sourceArray.add(((JSONObject) hitjson).getJSONObject("_source")) ;
        }

        ESResult result = new ESResult();
        result.setResultAggs(json.getJSONObject("aggregations"));
        result.setResultSource(sourceArray);
        result.setTotle(total);
        return result;
    }
    
}
